package com.yisu.auction.api.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.yisu.auction.api.core.mapper.*;
import com.yisu.auction.api.core.service.BaseService;
import com.yisu.auction.api.core.service.ITradeService;
import com.yisu.auction.api.core.service.impl.func.BalanceLogUtil;
import com.yisu.auction.api.domain.config.*;
import com.yisu.auction.api.domain.request.activityPackage.NewActivitiesRequest;
import com.yisu.auction.api.domain.request.memberPackage.MemberRequest;
import com.yisu.auction.api.domain.request.prizePackage.LatestAnnouncedRequest;
import com.yisu.auction.api.domain.request.prizePackage.PrizeDetailRequest;
import com.yisu.auction.api.domain.request.rechargePackage.RechargeRequest;
import com.yisu.auction.api.domain.request.tradePackage.TradeRequest;
import com.yisu.auction.api.domain.vo.activityPackageVos.LosingLotteryVo;
import com.yisu.auction.api.domain.vo.activityPackageVos.NewActivitiesRechargeRuleVo;
import com.yisu.auction.api.domain.vo.goodsInfoPackageVos.LatestAnnouncedVo;
import com.yisu.auction.api.domain.vo.indexPackageVos.SystemConfigVo;
import com.yisu.auction.ewf.common.enums.ResponseCode;
import com.yisu.auction.ewf.common.spring.SpringContext;
import com.yisu.auction.ewf.common.utils.StringUtil;
import com.yisu.auction.ewf.common.web.HttpWebClient;
import com.yisu.auction.ewf.common.web.JsonResult;
import com.yisu.auction.ewf.entity.*;
import org.apache.calcite.linq4j.Linq4j;
import org.apache.calcite.linq4j.function.Predicate1;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * author: 赵杰
 * Business Description：交易业务接口实现
 * createTime：2017/8/18
 */
@Service("ITradeService")
public class TradeServiceImpl extends BalanceLogUtil implements ITradeService {
    @Resource
    private PrizeMapper prizeMapper;
    @Resource
    private MemberMapper memberMapper;
    @Resource
    private OfferPriceLogMapper offerPriceLogMapper;
    @Resource
    private GoodsInfoMapper goodsInfoMapper;
    @Resource
    private MessageMapper messageMapper;
    @Resource
    private GoodsTypeMapper goodsTypeMapper;
    @Resource
    private NewActivitiesMapper newActivitiesMapper;
    @Resource
    private SystemConfigMapper systemConfigMapper;
    @Resource
    private com.yisu.auction.api.domain.config.SystemConfig systemConfig;

    /**
     * author: 赵杰
     * Business Description：出价业务，通过memberId,prizeId
     *
     * @param tradeRequest 含memberId,prizeId
     * @return
     */
    @Override
    public JsonResult offerPriceForJob(TradeRequest tradeRequest) {
        if(isStopPurchase()) {
            return new JsonResult(-1, "当前时间为禁拍时间！");
        }
        tradeRequest.setCurrentDate(offerPriceLogMapper.getDbDate());
        Prize prize = prizeMapper.selectByPrimaryKey(tradeRequest.getPrizeId());
        if (prize == null) {
            return new JsonResult(-999, "非法请求！");
        }
        if (prize.getStatus() == 1) {
            OfferPriceLog winnerLog = offerPriceLogMapper.getWinnerLogByPrizeId(tradeRequest.getPrizeId());
            if (winnerLog == null) {
                winnerLog = new OfferPriceLog();
                winnerLog.setTransactionPrice(BigDecimal.valueOf(0));
            }
//            GoodsInfo goodsInfo = goodsInfoMapper.selectByPrimaryKey(prize.getGoodsId());
//            if (goodsInfo.getStatus() == 1) {
//                return new JsonResult(-999, "商品已经停止竞拍");
//            }
            boolean savePercentage = ((prize.getPrice().doubleValue() * 0.1) - prize.getTransactionPrice().doubleValue()) < 0; //竞拍到1%的时候到达预开奖阶段
            Random random = new Random();
            int randomNum = random.nextInt(500);
            boolean openPrizeStatus = randomNum > 50 && randomNum < 60;
            if (((prize.getPrice().doubleValue() * 0.3 - prize.getTransactionPrice().doubleValue()) < 0)) {//强开奖
                savePercentage = true;
                openPrizeStatus = true;
            }
            if (savePercentage && openPrizeStatus) {
                Prize updatePrize = new Prize();
                updatePrize.setStatus((byte) 2);
                updatePrize.setId(prize.getId());
                updatePrize.setOpenPrizeType(0);
                updatePrize.setMemberId(Long.valueOf(tradeRequest.getMemberId()));
                updatePrize.setAnnounceTime(new Date());
                updatePrize.setTransactionPrice(winnerLog.getTransactionPrice().add(new BigDecimal(0.1)));
                prizeMapper.updateOpenPrizeStatus(updatePrize);
                if (!offerPriceCommon(winnerLog, prize, tradeRequest, OfferPriceLog.CurrencyTypeEnum.PRESENT.code, 0)) {
                    return new JsonResult(-1, "竞拍失败！");
                }
                return new JsonResult(1, "竞拍成功，等待开奖！", tradeRequest.getCurrentDate().getTime() + "");
            }
            if (!offerPriceCommon(winnerLog, prize, tradeRequest, OfferPriceLog.CurrencyTypeEnum.PRESENT.code, 0)) {
                return new JsonResult(-1, "竞拍失败！");
            }
            Prize updatePrize = new Prize();
            updatePrize.setId(prize.getId());
            updatePrize.setTransactionPrice(winnerLog.getTransactionPrice().add(new BigDecimal(0.1)));
            prizeMapper.updateByPrimaryKeySelective(updatePrize);
            return new JsonResult(0, "竞拍成功");
        }
        if (prize.getStatus() == 2) {
            return new JsonResult(-1, "竞拍失败");
        }
        if (prize.getStatus() == 3) {
            return new JsonResult(-999, "竞拍失败");
        }
        return new JsonResult(-100, "竞拍失败");
    }

    private boolean isStopPurchase() {
        if(systemConfig.isStopPurchase()) {
            Date date = new Date();
            int hour = date.getHours();
            if (hour >= 1 && hour < 6) {
                return true;
            }
        }

        return false;
    }

    /**
     * author: 赵杰
     * Business Description：出价业务，通过memberId,prizeId
     *
     * @param tradeRequest 含memberId,prizeId
     * @return
     */
    @Override
    public JsonResult offerPrice(TradeRequest tradeRequest) {
        tradeRequest.setCurrentDate(offerPriceLogMapper.getDbDate());
        JsonResult jsonResult = new JsonResult();
        /**
         * 优先检测竞品是否揭晓或状态是否为2，如果是揭晓状态，不能竞拍；  如果是2，则根据是否是虚拟用户和真实用户判断
         * 如果是2，真实用户进来，则不开将继续跟拍；如果是虚拟用户，则竞拍不成功直接返回，并通知服务进行直接开奖操作；
         * 如果是1，检测用户用户是否有余额；
         */
        if(isStopPurchase()) {
            return new JsonResult(-1, "当前时间为禁拍时间！");
        }
        Prize prize = prizeMapper.selectByPrimaryKey(tradeRequest.getPrizeId());
        Member member = memberMapper.selectByPrimaryKey(Long.valueOf(tradeRequest.getMemberId()));
        if (prize == null) {
            return new JsonResult(-999, "非法请求！");
        }
        if (member.getWallet().add(member.getPresentWallet()).intValue() <= 0) {
            return new JsonResult(-10, "用户余额不足！");
        }
        GoodsInfo goodsInfo = goodsInfoMapper.selectByPrimaryKey(prize.getGoodsId());
//        if (goodsInfo.getStatus() == 1) {
//            return new JsonResult(-999, "商品已经停止竞拍");
//        }
        if (prize.getStatus() == 1) {
            //判断开奖水位，如果水满了就开掉 返回-1即可；
            boolean isTrueOpenPrize = false;
            if (goodsInfo != null) {
                if ((goodsInfo.getAccumulativeBuyMoney().intValue() >= goodsInfo.getWaterLevel().intValue()) && member.getType() != 999) {
                    isTrueOpenPrize = true;
                }
            }
            OfferPriceLog winnerLog = offerPriceLogMapper.getWinnerLogByPrizeId(tradeRequest.getPrizeId());
            if (winnerLog == null) {
                winnerLog = new OfferPriceLog();
                winnerLog.setTransactionPrice(BigDecimal.valueOf(0));
            }
            if (isTrueOpenPrize) {
                Prize updatePrize = new Prize();
                updatePrize.setId(prize.getId());
                updatePrize.setStatus((byte) 2);
                updatePrize.setOpenPrizeType(isTrueOpenPrize ? 1 : 0);
                updatePrize.setMemberId(Long.valueOf(tradeRequest.getMemberId()));
                updatePrize.setAnnounceTime(new Date());
                updatePrize.setTransactionPrice(winnerLog.getTransactionPrice().add(new BigDecimal(0.1)));
                if (prizeMapper.updateOpenPrizeStatus(updatePrize) > 0) {
                    jsonResult = settleAccountsCommon(winnerLog, prize, tradeRequest, member);
                    if (jsonResult.getErrorCode() != 999) {
                        throw new RuntimeException("出价异常！");
                    }
                }
                if (!StringUtils.isEmpty(tradeRequest.getAppSign())) {
                    Map<String, String> maps = Maps.newConcurrentMap();
                    maps.put("prizeId", prize.getId() + "");
                    maps.put("lastPurchaseTime", tradeRequest.getCurrentDate().getTime() + "");
                    String resultJson = HttpWebClient.post(systemConfig.getAuctionJobUrl() + "/job/addOpenJob", maps);
                  /*  String resultJson = HttpWebClient.post( "http://192.168.206.225:8080/job/addOpenJob", maps);*/
                }
                return new JsonResult(1, "竞拍成功", tradeRequest.getCurrentDate().getTime() + "");
            }
            jsonResult = settleAccountsCommon(winnerLog, prize, tradeRequest, member);
            if (jsonResult.getErrorCode() != 999) {
                throw new RuntimeException("出价异常！");
            }
            Prize updatePrize = new Prize();
            updatePrize.setId(prize.getId());
            updatePrize.setTransactionPrice(winnerLog.getTransactionPrice().add(new BigDecimal(0.1)));
            prizeMapper.updateByPrimaryKeySelective(updatePrize);
            return new JsonResult(0, "竞拍成功");
        }
        if (prize.getStatus() == 2) {
            OfferPriceLog winnerLog = offerPriceLogMapper.getWinnerLogByPrizeId(tradeRequest.getPrizeId());
            if (winnerLog == null) {
                winnerLog = new OfferPriceLog();
                winnerLog.setTransactionPrice(BigDecimal.valueOf(0));
            }
            if (member.getType() != 999) {// 如果不需要开奖
                Prize updatePrize = new Prize();
                updatePrize.setId(prize.getId());
                updatePrize.setStatus((byte) 1);
                updatePrize.setMemberId(Long.valueOf(tradeRequest.getMemberId()));
                updatePrize.setAnnounceTime(new Date());
                updatePrize.setTransactionPrice(winnerLog.getTransactionPrice().add(new BigDecimal(0.1)));
                prizeMapper.updateOpenPrizeStatus(updatePrize);
                jsonResult = settleAccountsCommon(winnerLog, prize, tradeRequest, member);
                if (jsonResult.getErrorCode() != 999) {
                    throw new RuntimeException("出价异常！");
                }
                //prizeMapper.updateTransactionPrice(tradeRequest.getPrizeId());
                return new JsonResult(0, "竞拍成功");
            } else if (member.getType() == 999) {
                return new JsonResult(-1, "竞拍失败");
            }
        }
        if (prize.getStatus() == 3) {
            return new JsonResult(-999, "竞拍失败");
        }
        return new JsonResult(-100, "竞拍失败");
    }

    /**
     * author: 赵杰
     * Business Description：开竞拍结果
     *
     * @param tradeRequest
     * @return
     */
    @Override
    public JsonResult openPrizeResult(final TradeRequest tradeRequest) {
        OfferPriceLog winnerLog = offerPriceLogMapper.getWinnerLogByPrizeId(tradeRequest.getPrizeId());
        if (winnerLog == null)
            return new JsonResult(-1, "开奖失败");
        final Prize prize = prizeMapper.selectByPrimaryKey(tradeRequest.getPrizeId());
        if (prize.getStatus() != 2)
            return new JsonResult(-1, "未达到开奖条件");
        if (!StringUtils.isEmpty(tradeRequest.getLastPurchaseTime())) {
            if (!tradeRequest.getLastPurchaseTime().equals(winnerLog.getOfferPriceDate().getTime() + "")) {
                return new JsonResult(-1, "未达到开奖条件");
            }
        }
        Prize updatePrize = new Prize();
        updatePrize.setId(tradeRequest.getPrizeId());
        updatePrize.setStatus((byte) Prize.StatusTypeEnum.HAS_ANNOUNCED.code);
        updatePrize.setMemberId(winnerLog.getMemberId());
        updatePrize.setOrderStatus(0);
        updatePrize.setOfferPriceId(winnerLog.getId());
        updatePrize.setAnnounceTime(new Date());
        updatePrize.setTransactionPrice(winnerLog.getTransactionPrice());
        if (prizeMapper.actionOpenPrize(updatePrize) > 0) {
            final Member member = memberMapper.selectByPrimaryKey(prize.getMemberId());
            //不中返拍币,另起线程，异步执行
            ExecutorService executorService = Executors.newFixedThreadPool(1);
            Runnable syncRunnable = new Runnable() {
                @Override
                public void run() {
                    if (prize.getOpenPrizeType() == 1) {
                        goodsInfoMapper.cleanOpenPrizeWaterLevelByGoodsId(prize.getGoodsId());
                    }
                    returnWalletByPrizeId(tradeRequest.getPrizeId());
                    // TODO: 2017/9/7 用户中奖通知，待优化
                    pushMessage(member, prize);
                }
            };
            executorService.execute(syncRunnable);
            GoodsInfo goodsInfo = goodsInfoMapper.selectByPrimaryKey(prize.getGoodsId());
            //获取最大期号
            Integer maxTerm = goodsInfoMapper.getMaxTermByGoodsId(prize.getGoodsId()) + 1;
            GoodsInfo updateGoodsInfo = new GoodsInfo();
            updateGoodsInfo.setId(prize.getGoodsId());
            updateGoodsInfo.setTerm(maxTerm);
            updateGoodsInfo.setStatus(GoodsInfo.StatusEnum.SNATCH_TREASURE_ING.code);
            goodsInfoMapper.updateByPrimaryKeySelective(updateGoodsInfo);
            Prize insertPrize = new Prize();
            insertPrize.setCreateDate(new Date());
            insertPrize.setIsValid(true);
            insertPrize.setGoodsId(prize.getGoodsId());
            insertPrize.setStartTime(new Date());
            insertPrize.setPrice(goodsInfo.getPrice());
            insertPrize.setName(goodsInfo.getName());
            insertPrize.setGoodsTypeId(goodsInfo.getGoodsTypeId());
            insertPrize.setTerm(maxTerm);
            insertPrize.setImage(goodsInfo.getImages());
            insertPrize.setStatus((byte) Prize.StatusTypeEnum.SNATCH_TREASURE_ING.code);
            insertPrize.setIsTen(goodsInfo.getIsTen());
            insertPrize.setIsRechargeableCard(goodsInfo.getIsRechargeableCard());
            insertPrize.setGoodsDetail(goodsInfo.getDetail());
            prizeMapper.insertSelective(insertPrize);
            PrizeDetailRequest prizeDetailRequest = new PrizeDetailRequest();
            prizeDetailRequest.setGoodsId(insertPrize.getGoodsId());
            prizeDetailRequest.setTerm(maxTerm);
            Long prizeId = prizeMapper.getPrizeIdByGoodsIdAndTerm(prizeDetailRequest);
            if (prizeId != null && prizeId > 0) {
                Map<String, String> maps = Maps.newConcurrentMap();
                maps.put("prizeId", prizeId + "");
                String resultJson = HttpWebClient.post(systemConfig.getAuctionJobUrl() + "/job/addJob", maps);
              /*  String resultJson = HttpWebClient.post( "http://192.168.206.225:8080/job/addJob", maps);*/
                JsonResult jsonResult = JSON.parseObject(resultJson, JsonResult.class);
                if (jsonResult != null) {
                    System.out.println(resultJson);
                }
            }
            return new JsonResult(prizeId);
        }
        return new JsonResult(-1, "开奖失败");
    }


    /**
     * author: 赵杰
     * Business Description： 结算方法提取
     *
     * @param tradeRequest
     * @return
     */
    protected JsonResult settleAccountsCommon(OfferPriceLog winnerLog, Prize prize, TradeRequest tradeRequest, Member member) {
        if (member.getPresentWallet().intValue() > 0) {
            if (memberMapper.deductPresentWallet(Long.parseLong(tradeRequest.getMemberId())) <= 0)
                return new JsonResult(-10, "用户余额不足！");
            if (!offerPriceCommon(winnerLog, prize, tradeRequest, OfferPriceLog.CurrencyTypeEnum.PRESENT.code, (member.getType() != 999 ? 1 : 0))) {
                return new JsonResult(-1, "竞拍失败！");
            }
        } else {
            if (member.getWallet().intValue() > 0) {
                if (memberMapper.deductWallet(Long.parseLong(tradeRequest.getMemberId())) > 0) {
                    if (!offerPriceCommon(winnerLog, prize, tradeRequest, OfferPriceLog.CurrencyTypeEnum.OFFICIAL.code, (member.getType() != 999 ? 1 : 0))) {
                        return new JsonResult(-1, "竞拍失败！");
                    }
                } else {
                    return new JsonResult(-10, "用户余额不足！");
                }
            }
        }
        return new JsonResult(999, "竞拍成功！");
    }

    /**
     * author: 赵杰
     * Business Description：出价业务提取公共类
     *
     * @param tradeRequest
     * @param currencyType 拍币类型 1真实拍币 2赠送拍币
     * @param userType     用户类型 1真实用户 0虚拟用户
     * @return
     */
    protected boolean offerPriceCommon(OfferPriceLog winnerLog, Prize prize, TradeRequest tradeRequest, Integer currencyType, Integer userType) {
        //添加出价记录表
        OfferPriceLog offerPriceLog = new OfferPriceLog();
        offerPriceLog.setCreateDate(tradeRequest.getCurrentDate());
        offerPriceLog.setCurrencyType(currencyType);
        offerPriceLog.setIsValid(true);
        offerPriceLog.setMemberId(Long.valueOf(tradeRequest.getMemberId()));
        offerPriceLog.setOfferPrice(BigDecimal.valueOf(1));
        offerPriceLog.setOfferPriceDate(tradeRequest.getCurrentDate());
        offerPriceLog.setResult(OfferPriceLog.AuctionStatusEnum.UNDETERMIND.code);
        offerPriceLog.setPrizeId(tradeRequest.getPrizeId());
        offerPriceLog.setPrizePriceSort(0);
        offerPriceLog.setTransactionPrice(winnerLog.getTransactionPrice().add(new BigDecimal("0.1")));
        //出价成功，将其余人out出局
        if (offerPriceLogMapper.insert(offerPriceLog) > 0) {
            if (userType == 1 && currencyType == 1) {
                //追加单品销售水位
                goodsInfoMapper.updateAccumulativeBuyMoneyByGoodsId(prize.getGoodsId());
                //追加用户累计消费金额
                memberMapper.updateConsumptionAmount(Long.parseLong(tradeRequest.getMemberId()));
            }
            return true;
        }
        return false;
    }


    /**
     * author: 赵杰
     * Business Description：不中奖返拍币业务
     *
     * @param prizeId
     */
    protected void returnWalletByPrizeId(long prizeId) {
        /**
         * 获取当前期不中奖用户列表及所花费的金额，直接终止进钱包（拍币/.赠币）
         */
        //新用户不中返现合并写法
        boolean isActive = false;
        Prize prize = prizeMapper.selectByPrimaryKey(prizeId);
        if (prize != null) {
            GoodsType goodsType = goodsTypeMapper.selectByPrimaryKey(prize.getGoodsTypeId());
            if (goodsType.getName().contains("新手")) {
                isActive = true;
            }
        }
        if (isActive) {
            final NewActivitiesRequest newActivitiesRequest = new NewActivitiesRequest();
            newActivitiesRequest.setMemberId(String.valueOf(prize.getMemberId()));
            newActivitiesRequest.setPrizeId(prize.getId());
            List<NewActivities> newActivities = newActivitiesMapper.getNoWinRecord(newActivitiesRequest);
            for (final NewActivities item : newActivities) {
                Member member = memberMapper.selectByPrimaryKey(item.getMemberId());
                if (member == null) {
                    continue;
                }
                SystemConfigVo configValue = systemConfigMapper.getSystemConfigByKey("NewActivitiesRechargeRule");
                List<NewActivitiesRechargeRuleVo> newUserRechargeVos = JSON.parseArray(configValue.getConfigValue(), NewActivitiesRechargeRuleVo.class);
                if (CollectionUtils.isEmpty(newUserRechargeVos)) {
                    continue;
                }
                NewActivitiesRechargeRuleVo newActivitiesRechargeRuleVo = Linq4j.asEnumerable(newUserRechargeVos).where(new Predicate1<NewActivitiesRechargeRuleVo>() {
                    @Override
                    public boolean apply(NewActivitiesRechargeRuleVo newActivitiesRechargeRuleVo) {
                        return newActivitiesRechargeRuleVo.getRechargeAmount().equals(item.getRechargeObj());
                    }
                }).firstOrDefault();
                if (newActivitiesRechargeRuleVo == null) {
                    continue;
                }
                returnWalletCommon(member, new BigDecimal(newActivitiesRechargeRuleVo.getReturnAmount()), prizeId);
            }
        } else {
            List<LosingLotteryVo> losingLotteryVos = offerPriceLogMapper.getLosingLotteryByPrizeId(prizeId);
            if (!CollectionUtils.isEmpty(losingLotteryVos)) {
                for (LosingLotteryVo losingLotteryVo : losingLotteryVos) {
                    Member member = memberMapper.selectByPrimaryKey(losingLotteryVo.getMemberId());
                    if (member == null) {
                        continue;
                    }
                    returnWalletCommon(member, losingLotteryVo.getOfferPrice().multiply(BigDecimal.valueOf(0.3)), prizeId);
                }
            }
        }
    }

    /**
     * 不中返现返还拍币
     *
     * @param member     会员
     * @param operateNum 操作值
     * @param prizeId    竞品ID
     */
    protected void returnWalletCommon(Member member, BigDecimal operateNum, long prizeId) {
        addMemberWallet(member, operateNum, prizeId, BalanceLog.WalletTypeEnum.PRESENT_WALLET.code, "【不中返现】");
    }

    protected void pushMessage(Member member, Prize prize) {
        Message message = new Message();
        message.setCreateDate(new Date());
        String content = "恭喜<font color=#2A93E8>" + StringUtil.hideUserName(member.getNickname()) + "</font>拍得<font color=#0000FF>" + prize.getName() + "</font>";
        message.setContent(content);
        message.setIsValid(true);
        message.setTitle("拍卖头条");
        message.setPrizeId(prize.getId());
        message.setMemberId(member.getId());
        messageMapper.insertSelective(message);
        if (member.getType() != 999) {//只有真实用户，才可推送
            String pushContent = "恭喜您，拍得" + prize.getName() + ",快取查收吧";
            addSmsPush(pushContent, member.getMobile(), (byte) 2, member.getId(), prize.getId(), 0, new Date());
            String systemNoticeTitle = "恭喜您,中奖了！";
            addSystemNotice(pushContent, member.getId(), systemNoticeTitle, systemNoticeTitle, 2);
        }
    }
}
